﻿using System;
using System.Collections;
using System.Diagnostics;
using System.Text;
using System.Xml;
using BrnMall.Core;
using BrnMall.Manager.Manager.Order;
using BrnMall.Manager.Manager.Store;
using BrnMall.Manager.Manager.WeApp;
using BrnMall.Services;
using QIDong.WeApp.Models;
using QIDong.WeApp.Util;
using WeiTap.Restful;
using BrnMall.Manager.Domain.User;
using BrnMall.Manager.Manager.User;
using BrnMall.Sdk.WeiXin.Psbc;
using Newtonsoft.Json;
using BrnMall.Manager.Manager.Ship;

namespace QIDong.WeApp.Controllers
{
    /// <summary>
    /// 微信支付
    /// </summary>
    public class WeChatController : WebApi
    {
        #region 商品购买
        /// <summary>
        /// 微信支付
        /// </summary>
        /// <param name="storeId"></param>
        /// <param name="uid"></param>
        /// <param name="oid"></param>
        /// <returns></returns>
        public WeChatPayOutDto Pay(int storeId, int uid, int oid)
        {
            try
            {
                var orderInfo = Orders.GetOrderByOid(oid);
                if (orderInfo == null)
                    throw new Exception("订单不存在，或者不是待支付状态");
                if (orderInfo.OrderState != (int) OrderState.WaitPaying)
                {
                    throw new ApiException(ExceptionCode.Redirect,"当前无需支付，直接跳转");
                }
                var oa = OAuths.GetOAuthUserByUid(uid);
                if (string.IsNullOrEmpty(oa?.OpenId))
                    throw new Exception("没找到相关登录信息OpenId");
                //店铺微信相关设置
                var partUserInfo = Users.GetPartUserById(uid);
                string appid;
                string mchId;
                string mchKey;

                if (partUserInfo.StoreAppId != 0)//自动打包
                {
                    var auth = AppAuthorizationManager.GetAppAuthorizationByStoreAppId(partUserInfo.StoreAppId);
                    var paysetting = StoreApplicationManager.GetStoreApplicationPaySetting(partUserInfo.StoreAppId);
                    if (paysetting == null)
                        throw new Exception("请设置小程序的微信支付信息");
                    if (auth == null)
                        throw new Exception("小程序平台授权失败");
                    appid = auth.Authorizer_Appid;
                    if (paysetting.PayType == 0)
                    {
                        mchId = paysetting.MchId;
                        mchKey = paysetting.MchKey;
                        if (string.IsNullOrEmpty(appid) || string.IsNullOrEmpty(mchId) || string.IsNullOrEmpty(mchKey))
                            throw new Exception("微信支付配置信息错误");
                        return WeixinPay(orderInfo.Oid, orderInfo.SurplusMoney, oa.OpenId, appid, mchId, mchKey,
                            $"https://{BMAConfig.MallConfig.SiteUrl}/api/wechat/notify");
                    }

                    mchId = paysetting.PsbcMchId;
                    mchKey = paysetting.PsbcMchKey;
                    if (string.IsNullOrEmpty(appid) || string.IsNullOrEmpty(mchId) || string.IsNullOrEmpty(mchKey))
                        throw new Exception("微街支付配置信息错误");
                    return PsbcPay(orderInfo.Oid, orderInfo.SurplusMoney, oa.OpenId, appid, mchId, mchKey,
                        $"https://{BMAConfig.MallConfig.SiteUrl}/api/wechat/PsbcNotify");


                }

                var wxapp = StoreWxAppManager.GetStoreDefaultWxAppById(storeId, partUserInfo.WeAppId);
                if (string.IsNullOrEmpty(wxapp?.WeAppId) || string.IsNullOrEmpty(wxapp.WeAppSecret) || string.IsNullOrEmpty(wxapp.MchId) || string.IsNullOrEmpty(wxapp.MchKey))
                    throw new Exception("请登录商户后台设置小程序AppID,AppSecret,MchID,MchKey");
                appid = wxapp.WeAppId;
                if (wxapp.PayType == 0)
                {
                    mchId = wxapp.MchId;
                    mchKey = wxapp.MchKey;
                    if (string.IsNullOrEmpty(appid) || string.IsNullOrEmpty(mchId) || string.IsNullOrEmpty(mchKey))
                        throw new Exception("微信支付配置信息错误");
                    return WeixinPay(orderInfo.Oid, orderInfo.SurplusMoney, oa.OpenId, appid, mchId, mchKey,
                        $"https://{BMAConfig.MallConfig.SiteUrl}/api/wechat/notify");
                }

                mchId = wxapp.PsbcMchId;
                mchKey = wxapp.PsbcMchKey;
                if (string.IsNullOrEmpty(appid) || string.IsNullOrEmpty(mchId) || string.IsNullOrEmpty(mchKey))
                    throw new Exception("微街支付配置信息错误");
                return PsbcPay(orderInfo.Oid, orderInfo.SurplusMoney, oa.OpenId, appid, mchId, mchKey,
                    $"https://{BMAConfig.MallConfig.SiteUrl}/api/wechat/PsbcNotify");

            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }

        }

        /// <summary>
        /// 通知调用
        /// </summary>
        public string Notify()
        {
            BrnMall.Sdk.WeiXin.Tool.LogUtil.WriteLog("自动配送：回调开始");
            
            Trace.TraceInformation(this.RequestValues.ContentType);
            var formBody = Encoding.UTF8.GetString(this.RequestValues.FormBody);
            //创建ResponseHandler实例
            ResponseHandler resHandler = new ResponseHandler(formBody);


            //判断签名
            try
            {

                #region 协议参数=====================================
                //--------------协议参数--------------------------------------------------------
                //SUCCESS/FAIL此字段是通信标识，非交易标识，交易是否成功需要查
                string return_code = resHandler.getParameter("return_code");
                //返回信息，如非空，为错误原因签名失败参数格式校验错误
                string return_msg = resHandler.getParameter("return_msg");
                //微信分配的小程序 ID
                string appid = resHandler.getParameter("appid");

                //以下字段在 return_code 为 SUCCESS 的时候有返回--------------------------------
                //微信支付分配的商户号
                string mch_id = resHandler.getParameter("mch_id");
                //微信支付分配的终端设备号
                string device_info = resHandler.getParameter("device_info");
                //微信分配的公众账号 ID
                string nonce_str = resHandler.getParameter("nonce_str");
                //业务结果 SUCCESS/FAIL
                string result_code = resHandler.getParameter("result_code");
                //错误代码 
                string err_code = resHandler.getParameter("err_code");
                //结果信息描述
                string err_code_des = resHandler.getParameter("err_code_des");

                //以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回---------------
                //-------------业务参数---------------------------------------------------------
                //用户在商户 appid 下的唯一标识
                string openid = resHandler.getParameter("openid");
                //用户是否关注公众账号，Y-关注，N-未关注，仅在公众账号类型支付有效
                string is_subscribe = resHandler.getParameter("is_subscribe");
                //JSAPI、NATIVE、MICROPAY、APP
                string trade_type = resHandler.getParameter("trade_type");
                //银行类型，采用字符串类型的银行标识
                string bank_type = resHandler.getParameter("bank_type");
                //订单总金额，单位为分
                string total_fee = resHandler.getParameter("total_fee");
                //货币类型，符合 ISO 4217 标准的三位字母代码，默认人民币：CNY
                string fee_type = resHandler.getParameter("fee_type");
                //微信支付订单号
                string transaction_id = resHandler.getParameter("transaction_id");
                //商户系统的订单号，与请求一致。
                string out_trade_no = resHandler.getParameter("out_trade_no");
                //商家数据包，原样返回
                string attach = resHandler.getParameter("attach");
                //支 付 完 成 时 间 ， 格 式 为yyyyMMddhhmmss，如 2009 年12 月27日 9点 10分 10 秒表示为 20091227091010。时区为 GMT+8 beijing。该时间取自微信支付服务器
                string time_end = resHandler.getParameter("time_end");

                #endregion
                //支付成功
                if (!out_trade_no.Equals("") && return_code.Equals("SUCCESS") && result_code.Equals("SUCCESS"))
                {
                    Trace.TraceInformation("Notify 页面  支付成功，支付信息：商家订单号：" + out_trade_no + "、支付金额(分)：" + total_fee + "、自定义参数：" + attach);

                    /**
                     *  这里输入用户逻辑操作，比如更新订单的支付状态
                     * 
                     * **/

                    int oid = Convert.ToInt32(StringHelper.SubString(out_trade_no, out_trade_no.Length - 10));
                    OrderInfo orderInfo = Orders.GetOrderByOid(oid);
                    
                    //订单状态
                    int orderState = orderInfo.OrderState;

                    if (orderInfo.SurplusMoney <= TypeHelper.StringToDecimal(total_fee))
                    {
                        if (orderInfo.SurplusMoney > 0 && orderInfo.OrderState == (int)OrderState.WaitPaying)
                        {
                            Orders.PayOrder(orderInfo.Oid,
                                orderInfo.RegionId > 0 ? OrderState.PreProducting : OrderState.Received, transaction_id,
                                "wechatpay", "微信支付", DateTime.Now);
                            OrderActions.CreateOrderAction(new OrderActionInfo()
                            {
                                Oid = orderInfo.Oid,
                                Uid = orderInfo.Uid,
                                RealName = Users.GetPartUserById(orderInfo.Uid)?.NickName,
                                ActionType = (int)OrderActionType.Pay,
                                ActionTime = TypeHelper.StringToDateTime(time_end),
                                ActionDes = "你使用微信支付订单成功，微信交易号为:" + transaction_id
                            });
                            if (orderInfo.RegionId > 0)
                            {
                                OrderActions.CreateOrderAction(new OrderActionInfo()
                                {
                                    Oid = orderInfo.Oid,
                                    Uid = orderInfo.Uid,
                                    RealName = Users.GetPartUserById(orderInfo.Uid)?.NickName,
                                    ActionType = (int)OrderActionType.Pay,
                                    ActionTime = TypeHelper.StringToDateTime(time_end),
                                    ActionDes = "您的订单已经确认,正在备货中"
                                });

                                Ships.AutoShip(orderInfo, time_end); //达达配送
                            }
                            else
                            {
                                OrderActions.CreateOrderAction(new OrderActionInfo()
                                {
                                    Oid = orderInfo.Oid,
                                    Uid = orderInfo.Uid,
                                    RealName = Users.GetPartUserById(orderInfo.Uid)?.NickName,
                                    ActionType = (int)OrderActionType.Receive,
                                    ActionTime = TypeHelper.StringToDateTime(time_end),
                                    ActionDes = "订单没有配送地址，自动收货"
                                });
                                Distributors.CaculateBrokerage(orderInfo);
                            }
                                
                        }

                    }

                    #region  余额支付扣款 2017-11-22

                    //限制只调用一次,防止重复调用
                    if (orderState == 20)
                    {
                        //扣款，并添加记录
                        decimal payCash = OrderManager.GetPayCash(orderInfo.Oid);
                        if (payCash > 0)
                            CashOrders.ConsumeCash(orderInfo.Uid, orderInfo.StoreId, payCash, "消费扣款");
                    }
                    #endregion

                    Trace.TraceInformation("============ 单次支付结束 ===============");


                    return "success";
                }
                else
                {
                    Trace.TraceInformation("Notify 页面  支付失败，支付信息   total_fee= " + total_fee + "、err_code_des=" + err_code_des + "、result_code=" + result_code);
                    return string.Empty;
                }

            }
            catch (Exception ee)
            {
                Trace.TraceInformation("Notify 页面  发送异常错误：" + ee.Message);
                return string.Empty;
            }

            return "success";
        }
        #endregion

        #region 会员充值
        /// <summary>
        /// 发起微信充值
        /// </summary>
        /// <param name="storeId"></param>
        /// <param name="uid"></param>
        /// <param name="oid"></param>
        /// <returns></returns>
        public WeChatPayOutDto CashPay(int storeId, int uid, int oid)
        {
            CashOrder orderInfo = CashOrderManager.Get(oid);

            if (orderInfo == null || orderInfo.OrderState != (int)OrderState.WaitPaying)
                throw new Exception("订单不存在，或者不是待支付状态");
            try
            {
                var oa = OAuths.GetOAuthUserByUid(uid);
                if (string.IsNullOrEmpty(oa?.OpenId))
                    throw new Exception("没找到相关登录信息OpenId");

                //店铺微信相关设置
                var partUserInfo = Users.GetPartUserById(uid);
                string appid;
                string mchId;
                string mchKey;

                if (partUserInfo.StoreAppId != 0)//自动打包
                {
                    var auth = AppAuthorizationManager.GetAppAuthorizationByStoreAppId(partUserInfo.StoreAppId);
                    var paysetting = StoreApplicationManager.GetStoreApplicationPaySetting(partUserInfo.StoreAppId);
                    if (paysetting == null)
                        throw new Exception("请设置小程序的微信支付信息");
                    if (auth == null)
                        throw new Exception("小程序平台授权失败");
                    appid = auth.Authorizer_Appid;
                    if (paysetting.PayType == 0)
                    {
                        mchId = paysetting.MchId;
                        mchKey = paysetting.MchKey;
                        if (string.IsNullOrEmpty(appid) || string.IsNullOrEmpty(mchId) || string.IsNullOrEmpty(mchKey))
                            throw new Exception("微信支付配置信息错误");
                        return WeixinPay(orderInfo.id, orderInfo.OrderAmount, oa.OpenId, appid, mchId, mchKey,
                            $"https://{BMAConfig.MallConfig.SiteUrl}/api/wechat/CashNotify");
                    }

                    mchId = paysetting.PsbcMchId;
                    mchKey = paysetting.PsbcMchKey;
                    if (string.IsNullOrEmpty(appid) || string.IsNullOrEmpty(mchId) || string.IsNullOrEmpty(mchKey))
                        throw new Exception("微街支付配置信息错误");
                    return PsbcPay(orderInfo.id, orderInfo.OrderAmount, oa.OpenId, appid, mchId, mchKey,
                        $"https://{BMAConfig.MallConfig.SiteUrl}/api/wechat/CashPsbcNotify");


                }

                var wxapp = StoreWxAppManager.GetStoreDefaultWxAppById(storeId, partUserInfo.WeAppId);
                if (string.IsNullOrEmpty(wxapp?.WeAppId) || string.IsNullOrEmpty(wxapp.WeAppSecret) || string.IsNullOrEmpty(wxapp.MchId) || string.IsNullOrEmpty(wxapp.MchKey))
                    throw new Exception("请登录商户后台设置小程序AppID,AppSecret,MchID,MchKey");
                appid = wxapp.WeAppId;
                if (wxapp.PayType == 0)
                {
                    mchId = wxapp.MchId;
                    mchKey = wxapp.MchKey;
                    if (string.IsNullOrEmpty(appid) || string.IsNullOrEmpty(mchId) || string.IsNullOrEmpty(mchKey))
                        throw new Exception("微信支付配置信息错误");
                    return WeixinPay(orderInfo.id, orderInfo.OrderAmount, oa.OpenId, appid, mchId, mchKey,
                        $"https://{BMAConfig.MallConfig.SiteUrl}/api/wechat/CashNotify");
                }

                mchId = wxapp.PsbcMchId;
                mchKey = wxapp.PsbcMchKey;
                if (string.IsNullOrEmpty(appid) || string.IsNullOrEmpty(mchId) || string.IsNullOrEmpty(mchKey))
                    throw new Exception("微街支付配置信息错误");
                return PsbcPay(orderInfo.id, orderInfo.OrderAmount, oa.OpenId, appid, mchId, mchKey,
                    $"https://{BMAConfig.MallConfig.SiteUrl}/api/wechat/CashPsbcNotify");
            }
            catch (Exception e)
            {
                throw;
            }
        }

        /// <summary>
        /// 通知调用（会员充值用）
        /// </summary>
        /// <returns></returns>
        public string CashNotify()
        {
            Trace.TraceInformation(this.RequestValues.ContentType);
            var formBody = Encoding.UTF8.GetString(this.RequestValues.FormBody);
            //创建ResponseHandler实例
            ResponseHandler resHandler = new ResponseHandler(formBody);

            //判断签名
            try
            {
                #region 协议参数=====================================
                //--------------协议参数--------------------------------------------------------
                //SUCCESS/FAIL此字段是通信标识，非交易标识，交易是否成功需要查
                string return_code = resHandler.getParameter("return_code");
                //返回信息，如非空，为错误原因签名失败参数格式校验错误
                string return_msg = resHandler.getParameter("return_msg");
                //微信分配的小程序 ID
                string appid = resHandler.getParameter("appid");

                //以下字段在 return_code 为 SUCCESS 的时候有返回--------------------------------
                //微信支付分配的商户号
                string mch_id = resHandler.getParameter("mch_id");
                //微信支付分配的终端设备号
                string device_info = resHandler.getParameter("device_info");
                //微信分配的公众账号 ID
                string nonce_str = resHandler.getParameter("nonce_str");
                //业务结果 SUCCESS/FAIL
                string result_code = resHandler.getParameter("result_code");
                //错误代码 
                string err_code = resHandler.getParameter("err_code");
                //结果信息描述
                string err_code_des = resHandler.getParameter("err_code_des");

                //以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回---------------
                //-------------业务参数---------------------------------------------------------
                //用户在商户 appid 下的唯一标识
                string openid = resHandler.getParameter("openid");
                //用户是否关注公众账号，Y-关注，N-未关注，仅在公众账号类型支付有效
                string is_subscribe = resHandler.getParameter("is_subscribe");
                //JSAPI、NATIVE、MICROPAY、APP
                string trade_type = resHandler.getParameter("trade_type");
                //银行类型，采用字符串类型的银行标识
                string bank_type = resHandler.getParameter("bank_type");
                //订单总金额，单位为分
                string total_fee = resHandler.getParameter("total_fee");
                //货币类型，符合 ISO 4217 标准的三位字母代码，默认人民币：CNY
                string fee_type = resHandler.getParameter("fee_type");
                //微信支付订单号
                string transaction_id = resHandler.getParameter("transaction_id");
                //商户系统的订单号，与请求一致。
                string out_trade_no = resHandler.getParameter("out_trade_no");
                //商家数据包，原样返回
                string attach = resHandler.getParameter("attach");
                //支 付 完 成 时 间 ， 格 式 为yyyyMMddhhmmss，如 2009 年12 月27日 9点 10分 10 秒表示为 20091227091010。时区为 GMT+8 beijing。该时间取自微信支付服务器
                string time_end = resHandler.getParameter("time_end");

                #endregion
                //支付成功
                if (!out_trade_no.Equals("") && return_code.Equals("SUCCESS") && result_code.Equals("SUCCESS"))
                {
                    Trace.TraceInformation(string.Format("Notify 页面 充值支付成功，方法：CashNotify() 参数：商家订单号：{0}、支付金额(分)：{1}、自定义参数：{2}", out_trade_no, total_fee, attach));

                    int oid = Convert.ToInt32(StringHelper.SubString(out_trade_no, out_trade_no.Length - 10));
                    CashOrder orderInfo = CashOrderManager.Get(oid);

                    if (orderInfo == null)
                    {
                        Trace.TraceInformation(string.Format("Notify 页面  找不到订单，订单ID：{0}", oid));
                    }
                    else
                    {
                        if (orderInfo.OrderAmount <= TypeHelper.StringToDecimal(total_fee))
                        {
                            if (orderInfo.OrderAmount > 0 && orderInfo.OrderState == (int)OrderState.WaitPaying)
                            {
                                //更新订单
                                CashOrders.PayOrder(orderInfo.id, OrderState.Confirmed, transaction_id, DateTime.Now);

                                OrderActions.CreateOrderAction(new OrderActionInfo()
                                {
                                    Oid = orderInfo.id,
                                    Uid = orderInfo.Uid,
                                    RealName = Users.GetPartUserById(orderInfo.Uid)?.NickName,
                                    ActionType = (int)OrderActionType.Pay,
                                    ActionTime = TypeHelper.StringToDateTime(time_end),
                                    ActionDes = "你使用微信支付充值成功，微信交易号为:" + transaction_id
                                });
                            }
                        }
                    }

                    Trace.TraceInformation("============ 单次支付结束 ===============");

                    return "success";
                }
                else
                {
                    Trace.TraceInformation("Notify 页面  支付失败，方法: CashNotify() 支付信息 total_fee= " + total_fee + "、err_code_des=" + err_code_des + "、result_code=" + result_code);
                    return string.Empty;
                }
            }
            catch (Exception ee)
            {
                Trace.TraceInformation(string.Format("Notify 页面 发送异常错误 方法: CashNotify() 错误消息：{0}", ee.Message));
                return string.Empty;
            }
        }
        /// <summary>
        /// 会员充值付邮惠付回调
        /// </summary>
        /// <returns></returns>
        public string CashPsbcNotify()
        {
            Trace.TraceInformation(this.RequestValues.ContentType);
            var formBody = Encoding.UTF8.GetString(this.RequestValues.FormBody);
            Trace.TraceInformation(formBody);

            //创建ResponseHandler实例
            ResponseHandler resHandler = new ResponseHandler(formBody);


            //判断签名
            try
            {

                #region 协议参数=====================================
                //--------------协议参数--------------------------------------------------------
                //SUCCESS/FAIL此字段是通信标识，非交易标识，交易是否成功需要查
                string status = resHandler.getParameter("status");

                //以下字段在 return_code 为 SUCCESS 的时候有返回--------------------------------

                //业务结果 SUCCESS/FAIL
                string result_code = resHandler.getParameter("result_code");


                //以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回---------------
                //-------------业务参数---------------------------------------------------------

                //订单总金额，单位为分
                string total_fee = resHandler.getParameter("total_fee");

                //微信支付订单号
                string transaction_id = resHandler.getParameter("transaction_id");
                //商户系统的订单号，与请求一致。
                string out_trade_no = resHandler.getParameter("out_trade_no");

                //支 付 完 成 时 间 ， 格 式 为yyyyMMddhhmmss，如 2009 年12 月27日 9点 10分 10 秒表示为 20091227091010。时区为 GMT+8 beijing。该时间取自微信支付服务器
                string time_end = resHandler.getParameter("time_end");

                #endregion
                //支付成功
                if (!out_trade_no.Equals("") && status.Equals("0") && result_code.Equals("0"))
                {

                    int oid = Convert.ToInt32(StringHelper.SubString(out_trade_no, out_trade_no.Length - 10));
                    CashOrder orderInfo = CashOrderManager.Get(oid);


                    if (orderInfo.OrderAmount <= TypeHelper.StringToDecimal(total_fee))
                    {
                        if (orderInfo.OrderAmount > 0 && orderInfo.OrderState == (int)OrderState.WaitPaying)
                        {
                            //更新订单
                            CashOrders.PayOrder(orderInfo.id, OrderState.Confirmed, transaction_id, DateTime.Now);

                            OrderActions.CreateOrderAction(new OrderActionInfo()
                            {
                                Oid = orderInfo.id,
                                Uid = orderInfo.Uid,
                                RealName = Users.GetPartUserById(orderInfo.Uid)?.NickName,
                                ActionType = (int)OrderActionType.Pay,
                                ActionTime = TypeHelper.StringToDateTime(time_end),
                                ActionDes = "你使用微街支付充值成功，微信交易号为:" + transaction_id
                            });
                        }
                    }


                    Trace.TraceInformation("============ 单次支付结束 ===============");

                    return "success";
                }


                return string.Empty;

            }
            catch (Exception ee)
            {
                Trace.TraceInformation(string.Format("Notify 页面 发送异常错误 方法: CashPsbcNotify() 错误消息：{0}", ee.Message));
                return string.Empty;
            }
        }
        #endregion

        #region 当面付
        /// <summary>
        /// 当面付
        /// </summary>
        /// <param name="storeId"></param>
        /// <param name="uid"></param>
        /// <param name="oid"></param>
        /// <returns></returns>
        public WeChatPayOutDto DirectPay(int storeId, int uid, int oid)
        {
            DirectPayment orderInfo = DirectPaymentManager.GetPaymentByPid(oid);

            if (orderInfo == null || orderInfo.OrderState != 0)
                throw new Exception("订单不存在，或者不是待支付状态");
            if(orderInfo.SurplusMoney<=0)
                throw new Exception("待支付金额为0，无需支付");
            try
            {
                var oa = OAuths.GetOAuthUserByUid(uid);
                if (string.IsNullOrEmpty(oa?.OpenId))
                    throw new Exception("没找到相关登录信息OpenId");

                //店铺微信相关设置
                var partUserInfo = Users.GetPartUserById(uid);
                string appid;
                string mchId;
                string mchKey;

                if (partUserInfo.StoreAppId != 0)//自动打包
                {
                    var auth = AppAuthorizationManager.GetAppAuthorizationByStoreAppId(partUserInfo.StoreAppId);
                    var paysetting = StoreApplicationManager.GetStoreApplicationPaySetting(partUserInfo.StoreAppId);
                    if (paysetting == null)
                        throw new Exception("请设置小程序的微信支付信息");
                    if (auth == null)
                        throw new Exception("小程序平台授权失败");
                    appid = auth.Authorizer_Appid;
                    if (paysetting.PayType == 0)
                    {
                        mchId = paysetting.MchId;
                        mchKey = paysetting.MchKey;
                        if (string.IsNullOrEmpty(appid) || string.IsNullOrEmpty(mchId) || string.IsNullOrEmpty(mchKey))
                            throw new Exception("微信支付配置信息错误");
                        return WeixinPay(orderInfo.Pid, orderInfo.SurplusMoney, oa.OpenId, appid, mchId, mchKey,
                            $"https://{BMAConfig.MallConfig.SiteUrl}/api/wechat/DirectNotify");
                    }

                    mchId = paysetting.PsbcMchId;
                    mchKey = paysetting.PsbcMchKey;
                    if (string.IsNullOrEmpty(appid) || string.IsNullOrEmpty(mchId) || string.IsNullOrEmpty(mchKey))
                        throw new Exception("微街支付配置信息错误");
                    return PsbcPay(orderInfo.Pid, orderInfo.SurplusMoney, oa.OpenId, appid, mchId, mchKey,
                        $"https://{BMAConfig.MallConfig.SiteUrl}/api/wechat/DirectPsbcNotify");


                }

                var wxapp = StoreWxAppManager.GetStoreDefaultWxAppById(storeId, partUserInfo.WeAppId);
                if (string.IsNullOrEmpty(wxapp?.WeAppId) || string.IsNullOrEmpty(wxapp.WeAppSecret) || string.IsNullOrEmpty(wxapp.MchId) || string.IsNullOrEmpty(wxapp.MchKey))
                    throw new Exception("请登录商户后台设置小程序AppID,AppSecret,MchID,MchKey");
                appid = wxapp.WeAppId;
                if (wxapp.PayType == 0)
                {
                    mchId = wxapp.MchId;
                    mchKey = wxapp.MchKey;
                    if (string.IsNullOrEmpty(appid) || string.IsNullOrEmpty(mchId) || string.IsNullOrEmpty(mchKey))
                        throw new Exception("微信支付配置信息错误");
                    return WeixinPay(orderInfo.Pid, orderInfo.SurplusMoney, oa.OpenId, appid, mchId, mchKey,
                        $"https://{BMAConfig.MallConfig.SiteUrl}/api/wechat/DirectNotify");
                }

                mchId = wxapp.PsbcMchId;
                mchKey = wxapp.PsbcMchKey;
                if (string.IsNullOrEmpty(appid) || string.IsNullOrEmpty(mchId) || string.IsNullOrEmpty(mchKey))
                    throw new Exception("微街支付配置信息错误");
                return PsbcPay(orderInfo.Pid, orderInfo.SurplusMoney, oa.OpenId, appid, mchId, mchKey,
                    $"https://{BMAConfig.MallConfig.SiteUrl}/api/wechat/DirectPsbcNotify");
            }
            catch (Exception e)
            {
                throw;
            }
        }

        /// <summary>
        /// 当面付回调
        /// </summary>
        /// <returns></returns>
        public string DirectNotify()
        {
            Trace.TraceInformation(this.RequestValues.ContentType);
            var formBody = Encoding.UTF8.GetString(this.RequestValues.FormBody);
            //创建ResponseHandler实例
            ResponseHandler resHandler = new ResponseHandler(formBody);

            //判断签名
            try
            {
                #region 协议参数=====================================
                //--------------协议参数--------------------------------------------------------
                //SUCCESS/FAIL此字段是通信标识，非交易标识，交易是否成功需要查
                string return_code = resHandler.getParameter("return_code");
                //返回信息，如非空，为错误原因签名失败参数格式校验错误
                string return_msg = resHandler.getParameter("return_msg");
                //微信分配的小程序 ID
                string appid = resHandler.getParameter("appid");

                //以下字段在 return_code 为 SUCCESS 的时候有返回--------------------------------
                //微信支付分配的商户号
                string mch_id = resHandler.getParameter("mch_id");
                //微信支付分配的终端设备号
                string device_info = resHandler.getParameter("device_info");
                //微信分配的公众账号 ID
                string nonce_str = resHandler.getParameter("nonce_str");
                //业务结果 SUCCESS/FAIL
                string result_code = resHandler.getParameter("result_code");
                //错误代码 
                string err_code = resHandler.getParameter("err_code");
                //结果信息描述
                string err_code_des = resHandler.getParameter("err_code_des");

                //以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回---------------
                //-------------业务参数---------------------------------------------------------
                //用户在商户 appid 下的唯一标识
                string openid = resHandler.getParameter("openid");
                //用户是否关注公众账号，Y-关注，N-未关注，仅在公众账号类型支付有效
                string is_subscribe = resHandler.getParameter("is_subscribe");
                //JSAPI、NATIVE、MICROPAY、APP
                string trade_type = resHandler.getParameter("trade_type");
                //银行类型，采用字符串类型的银行标识
                string bank_type = resHandler.getParameter("bank_type");
                //订单总金额，单位为分
                string total_fee = resHandler.getParameter("total_fee");
                //货币类型，符合 ISO 4217 标准的三位字母代码，默认人民币：CNY
                string fee_type = resHandler.getParameter("fee_type");
                //微信支付订单号
                string transaction_id = resHandler.getParameter("transaction_id");
                //商户系统的订单号，与请求一致。
                string out_trade_no = resHandler.getParameter("out_trade_no");
                //商家数据包，原样返回
                string attach = resHandler.getParameter("attach");
                //支 付 完 成 时 间 ， 格 式 为yyyyMMddhhmmss，如 2009 年12 月27日 9点 10分 10 秒表示为 20091227091010。时区为 GMT+8 beijing。该时间取自微信支付服务器
                string time_end = resHandler.getParameter("time_end");

                #endregion
                //支付成功
                if (!out_trade_no.Equals("") && return_code.Equals("SUCCESS") && result_code.Equals("SUCCESS"))
                {
                    Trace.TraceInformation(string.Format("Notify 页面 充值支付成功，方法：CashNotify() 参数：商家订单号：{0}、支付金额(分)：{1}、自定义参数：{2}", out_trade_no, total_fee, attach));

                    int oid = Convert.ToInt32(StringHelper.SubString(out_trade_no, out_trade_no.Length - 10));
                    DirectPayment orderInfo = DirectPaymentManager.GetPaymentByPid(oid);

                    if (orderInfo == null)
                    {
                        Trace.TraceInformation($"Notify 页面  找不到订单，订单ID：{oid}");
                    }
                    else
                    {
                        if (orderInfo.SurplusMoney <= TypeHelper.StringToDecimal(total_fee))
                        {
                            if (orderInfo.SurplusMoney > 0 && orderInfo.OrderState == 0)
                            {
                                //更新订单
                                DirectPaymentManager.PayOrder(orderInfo.Pid,  transaction_id);
                            }
                            
                            //扣款，并添加记录
                            if (orderInfo.PayCash > 0)
                                CashOrders.ConsumeCash(orderInfo.Uid, orderInfo.StoreId, orderInfo.PayCash, "消费扣款");
                        }
                    }

                    Trace.TraceInformation("============ 单次支付结束 ===============");

                    return "success";
                }
                else
                {
                    Trace.TraceInformation("Notify 页面  支付失败，方法: CashNotify() 支付信息 total_fee= " + total_fee + "、err_code_des=" + err_code_des + "、result_code=" + result_code);
                    return string.Empty;
                }
            }
            catch (Exception ee)
            {
                Trace.TraceInformation(string.Format("Notify 页面 发送异常错误 方法: CashNotify() 错误消息：{0}", ee.Message));
                return string.Empty;
            }
        }
        /// <summary>
        /// 当面付邮惠付回调
        /// </summary>
        /// <returns></returns>
        public string DirectPsbcNotify()
        {
            Trace.TraceInformation(this.RequestValues.ContentType);
            var formBody = Encoding.UTF8.GetString(this.RequestValues.FormBody);
            Trace.TraceInformation(formBody);

            //创建ResponseHandler实例
            ResponseHandler resHandler = new ResponseHandler(formBody);


            //判断签名
            try
            {

                #region 协议参数=====================================
                //--------------协议参数--------------------------------------------------------
                //SUCCESS/FAIL此字段是通信标识，非交易标识，交易是否成功需要查
                string status = resHandler.getParameter("status");

                //以下字段在 return_code 为 SUCCESS 的时候有返回--------------------------------

                //业务结果 SUCCESS/FAIL
                string result_code = resHandler.getParameter("result_code");


                //以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回---------------
                //-------------业务参数---------------------------------------------------------

                //订单总金额，单位为分
                string total_fee = resHandler.getParameter("total_fee");

                //微信支付订单号
                string transaction_id = resHandler.getParameter("transaction_id");
                //商户系统的订单号，与请求一致。
                string out_trade_no = resHandler.getParameter("out_trade_no");

                //支 付 完 成 时 间 ， 格 式 为yyyyMMddhhmmss，如 2009 年12 月27日 9点 10分 10 秒表示为 20091227091010。时区为 GMT+8 beijing。该时间取自微信支付服务器
                string time_end = resHandler.getParameter("time_end");

                #endregion
                //支付成功
                if (!out_trade_no.Equals("") && status.Equals("0") && result_code.Equals("0"))
                {

                    int oid = Convert.ToInt32(StringHelper.SubString(out_trade_no, out_trade_no.Length - 10));
                    DirectPayment orderInfo = DirectPaymentManager.GetPaymentByPid(oid);

                    if (orderInfo == null)
                    {
                        Trace.TraceInformation(string.Format("Notify 页面  找不到订单，订单ID：{0}", oid));
                    }
                    else
                    {
                        if (orderInfo.SurplusMoney <= TypeHelper.StringToDecimal(total_fee))
                        {
                            if (orderInfo.SurplusMoney > 0 && orderInfo.OrderState == 0)
                            {
                                //更新订单
                                DirectPaymentManager.PayOrder(orderInfo.Pid, transaction_id);
                            }
                        }
                        //扣款，并添加记录

                        if (orderInfo.PayCash > 0)
                            CashOrders.ConsumeCash(orderInfo.Uid, orderInfo.StoreId, orderInfo.PayCash, "消费扣款");
                    }


                    Trace.TraceInformation("============ 单次支付结束 ===============");

                    return "success";
                }


                return string.Empty;

            }
            catch (Exception ee)
            {
                Trace.TraceInformation(string.Format("Notify 页面 发送异常错误 方法: CashPsbcNotify() 错误消息：{0}", ee.Message));
                return string.Empty;
            }
        }
        #endregion

        #region 邮惠付
        /// <summary>
        /// 发起邮惠付支付通道请求
        /// </summary>
        private WeChatPayOutDto PsbcPay(int oid, decimal surplusMoney, string openId, string appId,
            string mchId, string mchKey, string notifyUrl)
        {
            //openId = "orcUF0SNZ39cW7Z4ZgbgMQbmbYHg";
            //appId = "wxb55ecc44bea4cc9b";
            //mchId = "10500000000795";
            //mchKey = "78CBEC4E30012721CA84D1F3C50499D0";

            #region 基本参数

            //商户订单号
            string outTradeNo = oid + Randoms.CreateRandomValue(10, true);
            //订单名称
            string subject = BMAConfig.MallConfig.SiteTitle + "购物";
            //付款金额
            string totalFee = ((int)(surplusMoney * 100)).ToString();

            //时间戳 
            string timeStamp = TenpayUtil.getTimestamp();
            //随机字符串 
            string nonceStr = TenpayUtil.getNoncestr();

            //创建支付应答对象
            RequestHandler packageReqHandler = new RequestHandler(System.Web.HttpContext.Current);
            //初始化
            packageReqHandler.init();
            //设置package订单参数  具体参数列表请参考官方pdf文档，请勿随意设置
            packageReqHandler.setParameter("service", "pay.weixin.smallpay");//
            packageReqHandler.setParameter("mch_id", mchId);
            packageReqHandler.setParameter("appid", appId);
            packageReqHandler.setParameter("out_trade_no", outTradeNo); //商家订单号
            packageReqHandler.setParameter("body", subject); //商品信息 127字符
            packageReqHandler.setParameter("sub_openid", openId);//
            packageReqHandler.setParameter("total_fee", totalFee); //商品金额,以分为单位(money * 100).ToString()
            packageReqHandler.setParameter("mch_create_ip", base.HostAddress);//
            packageReqHandler.setParameter("notify_url", notifyUrl);
            packageReqHandler.setParameter("nonce_str", nonceStr.ToLower());
            #endregion
            #region sign===============================
            string sign = packageReqHandler.CreateMd5Sign("key", mchKey);
            packageReqHandler.setParameter("sign", sign);
            string data = packageReqHandler.parseXML();
            Trace.TraceInformation("WeiPay 页面  package（XML）：" + data);
            string prepayXml = HttpUtil.Send(data, "http://open.szpsbc.com.cn/wxsmallpay.do", "text/html");
            Trace.TraceInformation("WeiPay 页面  package（Back_XML）：" + prepayXml);


            #endregion

            if (string.IsNullOrEmpty(prepayXml)) throw new Exception("网络异常");
            var xmlMap = new Hashtable();
            var xmlDoc = new XmlDocument();
            xmlDoc.LoadXml(prepayXml);
            Trace.TraceInformation(xmlDoc.OuterXml);
            var root = xmlDoc.SelectSingleNode("xml");
            if (root == null)
                throw new Exception("未找到相关的xml节点信息");
            var xnl = root.ChildNodes;
            foreach (XmlNode xnf in xnl)
            {
                xmlMap.Add(xnf.Name, xnf.InnerText);
            }
            var status = xmlMap["status"]?.ToString();
            var resultCode = xmlMap["result_code"]?.ToString();
            if (status == null || !status.Equals("0"))
                throw new Exception(xmlMap["message"]?.ToString() ?? "");
            if (resultCode == null || !resultCode.Equals("0"))
                throw new Exception(xmlMap["err_msg"]?.ToString() ?? "");
            var payInfo = JsonConvert.DeserializeObject<PayInfoResult>(xmlMap["pay_info"].ToString());
            if (payInfo == null) throw new Exception("");
            var result = new WeChatPayOutDto
            {
                timeStamp = payInfo.timeStamp,
                nonceStr = payInfo.nonceStr,
                prepayId = payInfo.package.Split('=')[1],
                paySign = payInfo.paySign
            };

            OrderManager.UpdatePrepayId(oid, result.prepayId);
            return result;

        }

        /// <summary>
        /// 邮惠付通知调用
        /// </summary>
        public string PsbcNotify()
        {
            Trace.TraceInformation(this.RequestValues.ContentType);
            var formBody = Encoding.UTF8.GetString(this.RequestValues.FormBody);
            Trace.TraceInformation(formBody);

            //创建ResponseHandler实例
            ResponseHandler resHandler = new ResponseHandler(formBody);


            //判断签名
            try
            {

                #region 协议参数=====================================
                //--------------协议参数--------------------------------------------------------
                //SUCCESS/FAIL此字段是通信标识，非交易标识，交易是否成功需要查
                string status = resHandler.getParameter("status");



                //以下字段在 return_code 为 SUCCESS 的时候有返回--------------------------------

                //业务结果 SUCCESS/FAIL
                string result_code = resHandler.getParameter("result_code");


                //以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回---------------
                //-------------业务参数---------------------------------------------------------

                //订单总金额，单位为分
                string total_fee = resHandler.getParameter("total_fee");

                //微信支付订单号
                string transaction_id = resHandler.getParameter("transaction_id");
                //商户系统的订单号，与请求一致。
                string out_trade_no = resHandler.getParameter("out_trade_no");

                //支 付 完 成 时 间 ， 格 式 为yyyyMMddhhmmss，如 2009 年12 月27日 9点 10分 10 秒表示为 20091227091010。时区为 GMT+8 beijing。该时间取自微信支付服务器
                string time_end = resHandler.getParameter("time_end");

                #endregion
                //支付成功
                if (!out_trade_no.Equals("") && status.Equals("0") && result_code.Equals("0"))
                {
                    int oid = Convert.ToInt32(StringHelper.SubString(out_trade_no, out_trade_no.Length - 10));
                    OrderInfo orderInfo = Orders.GetOrderByOid(oid);

                    //订单状态
                    int orderState = orderInfo.OrderState;

                    if (orderInfo.SurplusMoney <= TypeHelper.StringToDecimal(total_fee))
                    {
                        if (orderInfo.SurplusMoney > 0 && orderInfo.OrderState == (int)OrderState.WaitPaying)
                        {
                            Orders.PayOrder(orderInfo.Oid,
                                orderInfo.RegionId > 0 ? OrderState.PreProducting : OrderState.Received, transaction_id,
                                "psbcpay", "微街支付", DateTime.Now);
                            OrderActions.CreateOrderAction(new OrderActionInfo()
                            {
                                Oid = orderInfo.Oid,
                                Uid = orderInfo.Uid,
                                RealName = Users.GetPartUserById(orderInfo.Uid)?.NickName,
                                ActionType = (int)OrderActionType.Pay,
                                ActionTime = TypeHelper.StringToDateTime(time_end),
                                ActionDes = "你使用微街支付订单成功，微信交易号为:" + transaction_id
                            });
                            if (orderInfo.RegionId > 0)
                            {
                                OrderActions.CreateOrderAction(new OrderActionInfo()
                                {
                                    Oid = orderInfo.Oid,
                                    Uid = orderInfo.Uid,
                                    RealName = Users.GetPartUserById(orderInfo.Uid)?.NickName,
                                    ActionType = (int)OrderActionType.Pay,
                                    ActionTime = TypeHelper.StringToDateTime(time_end),
                                    ActionDes = "您的订单已经确认,正在备货中"
                                });
                            }
                        }

                    }

                    #region  余额支付扣款 2017-11-22

                    //限制只调用一次,防止重复调用
                    if (orderState == 20)
                    {
                        //扣款，并添加记录
                        decimal payCash = OrderManager.GetPayCash(orderInfo.Oid);
                        if (payCash > 0)
                            CashOrders.ConsumeCash(orderInfo.Uid, orderInfo.StoreId, payCash, "消费扣款");
                    }
                    #endregion
                    return "success";
                }
                return string.Empty;


            }
            catch (Exception ee)
            {
                Trace.TraceInformation("Notify 页面  发送异常错误：" + ee.Message);
                return string.Empty;
            }


        }
        #endregion

        #region 支付逻辑

        private WeChatPayOutDto WeixinPay(int oid, decimal surplusMoney, string openId, string appId,
            string mchId, string mchKey, string notifyUrl)
        {
            #region 基本参数

            //商户订单号
            string outTradeNo = oid + Randoms.CreateRandomValue(10, true);
            //订单名称
            string subject = BMAConfig.MallConfig.SiteTitle + "购物";
            //付款金额
            string totalFee = ((int)(surplusMoney * 100)).ToString();

            //时间戳 
            string timeStamp = TenpayUtil.getTimestamp();
            //随机字符串 
            string nonceStr = TenpayUtil.getNoncestr();


            //string notifyUrl = $"http://121.199.10.151:8022/api/wechat/notify";

            //创建支付应答对象
            RequestHandler packageReqHandler = new RequestHandler(System.Web.HttpContext.Current);
            //初始化
            packageReqHandler.init();
            //设置package订单参数  具体参数列表请参考官方pdf文档，请勿随意设置
            packageReqHandler.setParameter("body", subject); //商品信息 127字符
            packageReqHandler.setParameter("appid", appId);
            packageReqHandler.setParameter("mch_id", mchId);
            packageReqHandler.setParameter("nonce_str", nonceStr.ToLower());
            packageReqHandler.setParameter("notify_url", notifyUrl);
            packageReqHandler.setParameter("openid", openId);
            packageReqHandler.setParameter("out_trade_no", outTradeNo); //商家订单号
            packageReqHandler.setParameter("spbill_create_ip", base.HostAddress); //用户的公网ip，不是商户服务器IP
            packageReqHandler.setParameter("total_fee", totalFee); //商品金额,以分为单位(money * 100).ToString()
            packageReqHandler.setParameter("trade_type", "JSAPI");
            #endregion
            #region sign===============================
            string sign = packageReqHandler.CreateMd5Sign("key", mchKey);
            Trace.TraceInformation("WeiPay 页面  sign：" + sign);
            packageReqHandler.setParameter("sign", sign);
            string data = packageReqHandler.parseXML();
            Trace.TraceInformation("WeiPay 页面  package（XML）：" + data);

            string prepayXml = HttpUtil.Send(data, "https://api.mch.weixin.qq.com/pay/unifiedorder");
            Trace.TraceInformation("WeiPay 页面  package（Back_XML）：" + prepayXml);

            //获取预支付ID
            string prepayId = "";
            string package = "";
            XmlDocument xdoc = new XmlDocument();
            xdoc.LoadXml(prepayXml);
            XmlNode xn = xdoc.SelectSingleNode("xml");
            XmlNodeList xnl = xn.ChildNodes;
            var firtNode = xnl[0].InnerText;
            if (firtNode.Equals("fail", StringComparison.InvariantCultureIgnoreCase))
            {
                var message = xnl[1].InnerText;
                throw new Exception(message);
            }
            if (xnl.Count > 7)
            {
                prepayId = xnl[7].InnerText;
                package = $"prepay_id={prepayId}";
                Trace.TraceInformation("WeiPay 页面  package：" + package);
            }
            #endregion

            #region 构建小程序wx.requestPayment需要的参数
            RequestHandler paySignReqHandler = new RequestHandler(System.Web.HttpContext.Current);
            paySignReqHandler.setParameter("appId", appId);
            paySignReqHandler.setParameter("timeStamp", timeStamp);
            paySignReqHandler.setParameter("nonceStr", nonceStr);
            paySignReqHandler.setParameter("package", package);
            paySignReqHandler.setParameter("signType", "MD5");
            string paySign = paySignReqHandler.CreateMd5Sign("key", mchKey);
            var result = new WeChatPayOutDto
            {
                timeStamp = timeStamp,
                nonceStr = nonceStr,
                prepayId = prepayId,
                paySign = paySign
            };

            OrderManager.UpdatePrepayId(oid, prepayId);
            #endregion

            return result;
        }

        #endregion
    }
}